package org.tgcloud.group.web.websocket;


import com.qiniu.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMapping;
import org.tgcloud.group.core.RedisUtil;
import org.tgcloud.group.entity.LogInfo;
import org.tgcloud.group.repository.LogInfoMapper;

import javax.validation.constraints.NotNull;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 业务处理类
 *
 * @author ljg
 * @ ServerEndpoint 注解是一个类层次的注解，它的功能主要是将目前的类定义成一个websocket服务器端,
 * * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 * @date 2023.10.16
 */
@Slf4j
@Component
//@RequestMapping("/websocket/{userId}/{userType}")
@ServerEndpoint("/websocket/{userId}/{userType}")
public class WebSocketServer {

    /**
     * 当前在线人数
     * 字符串比较的是什么
     */
    private static AtomicInteger onlineCount = new AtomicInteger(0);

    private static AtomicInteger onlineAppCount = new AtomicInteger(0);

    /**
     * 存放每个客户端对应的 WebSocketServer 对象
     */
    private static CopyOnWriteArrayList<WebSocketServer> webSocketServers = new CopyOnWriteArrayList<>();

    private static ConcurrentHashMap<String,WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    private static ConcurrentHashMap<String,WebSocketServer> appWebSocketMap = new ConcurrentHashMap<>();

    private Session session;

    @Autowired
    private LogInfoMapper logInfoMapper;

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session,
                       @PathParam(value = "userId") String userId,
                       @PathParam(value = "userType") Integer userType) {
        WebSocketServer webSocketServer = webSocketMap.get(userId);
        if (null == webSocketServer){
            if(userType == 1){
                this.session = session;
                // 加入集合中
                appWebSocketMap.put(userId, this);
                // 在线人数+1
                int count = onlineAppCount.incrementAndGet();
                log.info("有新的app窗口开始监听：, 当前app在线人数为：{}, userId: {}, userType: {}", count, userId, userType);
            }else {
                this.session = session;
                // 加入集合中
                webSocketMap.put(userId, this);
                // 在线人数+1
                int count = onlineCount.incrementAndGet();
                log.info("有新的web窗口开始监听：, 当前web在线人数为：{}, userId: {}, userType: {}", count, userId, userType);
            }
        }
    }

    /**
     * 收到客服端消息后调用的方法
     *
     * @param message 客服端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session,
                          @PathParam(value = "userId") String userId,
                          @PathParam(value = "userType") Integer userType) {
//        log.info("收到来自窗口：{}, 消息内容：{},userId: {}", session.getMessageHandlers(), message, userId);
        if (!StringUtils.isNullOrEmpty(message)) {
            // 进行业务逻辑处理
        }
    }

    /**
     * `
     * 发生错误时调用的方法
     */
    @OnError
    public void onError(Session session, @PathParam(value = "userId") String userId,
                        @NotNull Throwable throwable) {
        log.error("发生错误");
        throwable.printStackTrace();
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(@PathParam(value = "userId") String userId,
                        @PathParam(value = "userType") Integer userType) {
        if (userType == 1){
            // 从集合中移除
            appWebSocketMap.remove(userId);
            // 在线人数-1
            int count = onlineAppCount.decrementAndGet();
            log.info("有一连接关闭！当前app在线人数为：{},用户：{}已退出", count, userId);
        }else {
            // 从集合中移除
            webSocketMap.remove(userId);
            // 在线人数-1
            int count = onlineCount.decrementAndGet();
            log.info("有一连接关闭！当前web在线人数为：{},用户：{}已退出", count, userId);
        }
    }

    /**
     * 实现服务器主动推送消息
     *
     * @param message 消息内容
     */
    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
            log.info("message:{}", message);
        } catch (IOException e) {
            log.error("websocket IO Exception");
            e.printStackTrace();
        }
    }


    /**
     * 发送消息到指定窗口 null则群发
     */
    public void sendInfo(String message) {
        for (WebSocketServer webSocketServer : WebSocketServer.getWebSocketServers()) {
            webSocketServer.sendMessage(message);
        }
        return;
    }

    public static Collection<WebSocketServer> getWebSocketServers() {
        return webSocketMap.values();
    }

    public void sendMsgToUserIdString(String msg, String userId, Short userType){
        if (userType == 1){
            // 发送给小程序用户
            appWebSocketMap.get(userId).sendMessage(msg);
        }else {
            webSocketMap.get(userId).sendMessage(msg);
        }
    }

    public void sendMsgToUserId(String msg, Integer userId, Short userType){
        LogInfo logInfo = logInfoMapper.selectByUserId(userId);
        if (null != logInfo){
            if (userType == 1){
                // 发送给小程序用户
                if (appWebSocketMap.containsKey(logInfo.getToken())){
                    appWebSocketMap.get(logInfo.getToken()).sendMessage(msg);
                }
            }else {
                // 发送给web用户
                if (webSocketMap.containsKey(logInfo.getToken())){
                    webSocketMap.get(logInfo.getToken()).sendMessage(msg);
                }
            }
        }
        System.out.println("websocket发送成功");
    }

    public void sendMsgToAllWebUser(String msg){
        for (String key : webSocketMap.keySet()){
            webSocketMap.get(key).sendMessage(msg);
        }
    }


}


